import { Sandpack } from '@/components'

# SuspenseInfiniteQuery

Just as [`<SuspenseQuery/>`](/docs/react-query/SuspenseQuery) makes useSuspenseQuery easier to use in jsx, `<SuspenseInfiniteQuery/>` serves to make useSuspenseInfiniteQuery easier to use in jsx.

```jsx /SuspenseInfiniteQuery/
import { SuspenseInfiniteQuery } from '@suspensive/react-query'
import { Suspense, ErrorBoundary } from '@suspensive/react'
import { PostListItem } from '~/components'

const InfinitePostsPage = ({ userId }) => (
  <ErrorBoundary fallback={({ error }) => <>{error.message}</>}>
    <Suspense fallback="loading...">
      <SuspenseInfiniteQuery {...postsInfiniteQueryOptions(userId)}>
        {({ data, fetchNextPage }) => (
          <>
            {data.pages.map((post) => (
              <PostListItem {...post} />
            ))}
            <button
              type="button"
              onClick={() => {
                fetchNextPage()
              }}
            >
              Load More
            </button>
          </>
        )}
      </SuspenseInfiniteQuery>
    </Suspense>
  </ErrorBoundary>
)
```

<Sandpack>

```tsx Example.tsx active
import React from 'react'
import { SuspenseInfiniteQuery } from '@suspensive/react-query'
import { Suspense, ErrorBoundary } from '@suspensive/react'
import { PostListItem } from './PostListItem'
import { postsInfiniteQueryOptions } from './queries'

export const Example = () => {
  return (
    <ErrorBoundary fallback={({ error }) => <>{error.message}</>}>
      <Suspense fallback={<div>Loading...</div>}>
        <div
          style={{
            display: 'flex',
            flexDirection: 'column',
            marginBottom: '50px',
          }}
        >
          <SuspenseInfiniteQuery
            {...postsInfiniteQueryOptions()}
            getNextPageParam={(lastPage, allPages) => {
              return lastPage.skip + lastPage.limit < lastPage.total
                ? allPages.length + 1
                : undefined
            }}
          >
            {({
              data: { pages },
              fetchNextPage,
              hasNextPage,
              isFetchingNextPage,
              isFetched,
            }) => (
              <>
                <ol>
                  {pages.map((page) =>
                    page.data.map((post) => (
                      <PostListItem key={post.id} {...post} />
                    ))
                  )}
                </ol>
                <button
                  onClick={() => fetchNextPage()}
                  disabled={!hasNextPage || isFetchingNextPage}
                >
                  {isFetchingNextPage
                    ? 'Loading more...'
                    : hasNextPage
                      ? 'Load More'
                      : 'Nothing more to load'}
                </button>
              </>
            )}
          </SuspenseInfiniteQuery>
        </div>
      </Suspense>
    </ErrorBoundary>
  )
}
```

```tsx PostListItem.tsx
import type { Post } from './api'

export const PostListItem = (props: Post) => {
  return <li style={{ marginBottom: '10px' }}>{props.title}</li>
}
```

```tsx queries.ts
import { infiniteQueryOptions } from '@suspensive/react-query'
import { getInfinitePosts } from './api'

export const postsInfiniteQueryOptions = () =>
  infiniteQueryOptions({
    queryKey: ['posts'],
    queryFn: ({ pageParam = 1 }) => getInfinitePosts(pageParam),
    getNextPageParam: (lastPage, allPages) =>
      lastPage.skip + lastPage.limit < lastPage.total
        ? allPages.length + 1
        : undefined,
  })
```

```tsx api.ts
export type Post = {
  userId: number
  id: number
  title: string
  body: string
}

export const getInfinitePosts = async (
  page: number
): Promise<{
  data: Post[]
  page: number
  total: number
  limit: number
  skip: number
}> => {
  const response = await fetch(
    `https://jsonplaceholder.typicode.com/posts?_page=${page}&_limit=10`
  )

  if (!response.ok) {
    throw new Error('An error occurred')
  }

  const data = await response.json()

  return {
    data,
    page,
    total: 100,
    limit: 10,
    skip: (page - 1) * 10,
  }
}
```

</Sandpack>

### Version History

| Version  | Changes                                                                                                                                   |
| -------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
| `v3.0.0` | `networkMode` has been fixed to `'always'`. For more details, please refer to the [Migration to v3 guide](./migration/migrate-to-v3.mdx). |
